using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UtilConstants;

public class InventoryGui : MonoBehaviour, IToggleGui, IClickableGui {
	private Rect curr;
	private int id = 0;

	private const float TOP_BORDER = 20;
	private const float LEFT_BORDER = 5;
	private const float RIGHT_BORDER = 5;
	private const float BOTTOM_BORDER = 20;
	private const float ITEM_SPACING = 5;
	private const float BOX_SIDE_LENGTH = 32;
	private const float CURRENCY_BAR_HEIGHT = 20;
	private static string TITLE = "Inventory";
	private static Color UNUSABLE_ITEM_ALPHA = new Color(1.0f, 1.0f, 1.0f, 0.4f);
	
	/* TODO: this will be changeable later */
	private const int NUM_ROWS = Inventory.NUM_ROWS;
	private const int NUM_COLS = Inventory.NUM_COLS;
	
	private ItemContainerGui boxes;
	public ToggleGui toggle { set; get; }
	private GlobalAccess globals;
	
	PlayerPersistence player;
	GuiMouseCursor cursor;
	GuiImages images;
	
	private Rect[] ItemBoxes;
	private Rect close_rect;
	
	MouseClickMemory left_click;
	
	const bool DEBUG = true;
	
	void Awake () {
		this.toggle = new ToggleGui(false);
		this.boxes = new ItemContainerGui(new Vector2(0, 0), InventoryGui.NUM_ROWS, InventoryGui.NUM_COLS);
		this.globals = new GlobalAccess();
	}
	
	void Start () {	
		this.curr = new Rect(150,30,
			this.boxes.width,
			this.boxes.height + InventoryGui.CURRENCY_BAR_HEIGHT);
		this.id = 0;
		
		this.ItemBoxes = new Rect[InventoryGui.NUM_COLS * InventoryGui.NUM_ROWS];
	}
	
	void OnGUI() {
		if (!this.toggle.IsOn) {
			return;
		}
		
		this.curr = GUI.Window (this.id, this.curr, DrawWindow, InventoryGui.TITLE);
	}
	
	bool AreGlobalsReady() {
		if (this.globals == null) {
			return false;
		}
		
		this.player = (PlayerPersistence)this.globals.GetGlobalComponent(typeof(PlayerPersistence));
		if (this.player == null) {
			return false;
		}
		
		this.cursor = (GuiMouseCursor)this.globals.GetGlobalComponent(typeof(GuiMouseCursor));
		if (this.cursor == null) {
			return false;
		}
		
		this.images = (GuiImages)this.globals.GetGlobalComponent(typeof(GuiImages));
		if (this.images == null) {
			return false;
		}
		
		return true;
	}
	
	private void LeftClickItemCheck(Event e) {
		int src_row;
		int src_col;
		int dst_row;
		int dst_col;
		
		if (!this.AreGlobalsReady()) {
			return;
		}
		
		if (!this.boxes.GetBoxFromPos (
				this.left_click.pos,
				out src_row,
				out src_col)) {
			return;
		}
		
		/* always undarken the item that's been clicked */
		this.boxes.UnsetBoxDarkened(src_row, src_col);
		
		if (!this.boxes.GetBoxFromPos (
				e.mousePosition,
				out dst_row,
				out dst_col)) {
			return;
		}
		
		/* Clicked down in one box, up in another (maybe the same one) */
		if ((src_row == dst_row) && (src_col == dst_col)) {
			return;
		}
		
		if (InventoryGui.DEBUG) {
			Debug.Log ("clicked down " + src_row + "," + src_col +
				"\nclicked up " + dst_row + "," + dst_col);
		}
		
		this.player.inventory.MoveItemStack(src_row, src_col, dst_row, dst_col);
	}
	
	void LeftClickDown(Event e) {
		int row;
		int col;
		ItemStack s;
		Texture2D icon;
		
		/* Save the fact that we down-clicked */
		this.left_click.down = true;
		this.left_click.pos = e.mousePosition;
		
		if (!this.AreGlobalsReady()) {
			return;
		}
	
		
		if (!this.boxes.GetBoxFromPos (
				this.left_click.pos,
				out row,
				out col)) {
			return;
		}
		
		this.boxes.SetBoxDarkened(row, col);
		
		s = this.player.inventory.GetItemStack (row, col);
		if (s == null) {
			return;
		}
		
		/* We mouse downed an item, we make it our cursor to "hold" it */
		icon = this.images.GetTexture(s.item.GetImagePath());
		if (icon == null) {
			return;
		}
		
		this.cursor.SetCursor(icon);
	}
	
	void LeftClickUp(Event e) {
	
		/* Handle mouse up event if we had previously mouse downed in the inv */
		if (this.left_click.down) {
			if (this.close_rect.Contains (e.mousePosition) &&
				this.close_rect.Contains (this.left_click.pos)) {
				this.toggle.IsOn = false;
			} else {
				this.LeftClickItemCheck(e);
			}
		}
		this.left_click.down = false;
		this.cursor.UnsetCursor();
	}
	
	public void LeftClick(Event e) {
		if (!this.AreGlobalsReady()) {
			return;
		}
		
		if (e.type == EventType.MouseDown) {
			this.LeftClickDown (e);
		} else if (this.left_click.down && (e.type == EventType.MouseUp)) {
			this.LeftClickUp(e);

		}
	}
	
	private void RightClickItem(int row, int col) {
		ItemStack s;
		
		if (InventoryGui.DEBUG) {
			Debug.Log ("clicked row " + row.ToString () +
				" col " + col.ToString ());
		}
		
		if (!this.AreGlobalsReady()) {
			return;
		}
				
		s = this.player.inventory.GetItemStack (row, col);
		if (s == null) {
			return;
		}
		
		if (InventoryGui.DEBUG) {
			Debug.Log ("clicked item " + s.item.DisplayName ());
		}
	}
	
	public void RightClick(Event e) {
		Vector2 gui_pos;
		bool found;
		Pair<int, int> row_and_col = new Pair<int, int>(0, 0);
			
		gui_pos = e.mousePosition;
		
		found = false;
		if (this.boxes.GetBoxFromPos (gui_pos,out row_and_col)) {
			found = true;
		}
		
		switch (e.type) {
		case EventType.MouseDown:
			if (found) {
				this.RightClickItem(row_and_col.Item1, row_and_col.Item2);
			}
			break;
		case EventType.MouseUp:
			break;
		default:
			/* should be unreachable */
			break;
		}
	}
	
	void DrawWindow(int id) {
		float top_border;
		int index;
		string currency;
		
		if (!this.toggle.IsOn) {
			return;
		}
		
		if (!this.AreGlobalsReady()) {
			return;
		}
		
		index = 0;
		for (int row=0; row<this.boxes.num_rows; row++) {
			for (int col=0; col<this.boxes.num_columns; col++) {
				ItemStack s;
				Rect box;
					
				box = this.boxes.GetBoxRect (row, col);
				
				this.ItemBoxes[index] = box;				
				GUI.Box (box, (string)null);
				
				s = this.player.inventory.GetItemStack (row, col);
				if (s != null) {
					Texture2D icon;
					
					icon = this.images.GetTexture(s.item.GetImagePath ());
					if (icon != null) {
						if (this.boxes.IsBoxDarkened(row, col)) {
							Color old_color = GUI.color;
						
							GUI.color = InventoryGui.UNUSABLE_ITEM_ALPHA;
							GUI.DrawTexture(box, icon);
							GUI.color = old_color;
						} else {
							GUI.DrawTexture(box, icon);
						}
					}
					
					GUI.Label(box, (string)s.amount.ToString ());
				}
				
				index++;
			}
		}
		
		/* A square in the top right */
		top_border = this.boxes.top_border;
		this.close_rect = new Rect(this.curr.width - top_border, 0,
								top_border,	top_border);
		GUI.Box (close_rect, "x");
		
		currency = "";
		foreach (Currency c in this.player.currency) {
			currency += c.amount.ToString () + c.GetSymbolString() + " ";
		}
		
		GUI.Box (new Rect(
			0, this.boxes.height,
			this.curr.width, InventoryGui.CURRENCY_BAR_HEIGHT),
			currency);
			
		
		/* Catch mouse clicks */
		GuiIO.HandleMouseClick(this, Event.current);	
		
		/* only drag by title bar */
		GUI.DragWindow(new Rect(0, 0, this.curr.width, InventoryGui.TOP_BORDER));
	}
}
